package com.kaibes.im;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.locks.ReentrantLock;

import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;

import com.kaibes.im.control.activity.KaibesActivity;
import com.kaibes.im.control.activity.LoginActivity;
import com.kaibes.im.control.activity.MainActivity;
import com.kaibes.im.control.service.KaibesService;
import com.kaibes.im.database.KaibesDataHelper;
import com.kaibes.im.model.KaibesFile;
import com.kaibes.im.model.SocketWorker;
import com.kaibes.im.model.SocketWorker.Task;
import com.kaibes.im.model.data.ChatListviewData;
import com.kaibes.im.model.data.ContactInformationData;
import com.kaibes.im.model.data.PluginListviewData;
import com.kaibes.im.model.data.UserInformationData;
import com.kaibes.im.utils.BitmapUtil;
import com.kaibes.im.utils.KaibesFilesUtil;
import com.kaibes.im.utils.SoundPoolUtil;
import com.kaibes.im.utils.StaticValuesUtil;
import com.kaibes.im.view.RoundImageView;
import com.kaibes.im.view.fragment.KaibesFragment;
import com.kaibes.im.view.fragment.MainFragment;

public class KaibesApplication extends Application {

    public static final String CHARSET = "UTF-8";
    private KaibesDataHelper databaseHelper;

    // 总数据
    private HashMap<String, ContactInformationData> contactInformationDatas;
    private HashMap<String, ContactInformationData> tempSearchDatas;

    // 会话列表数据
    private ArrayList<String> contactFragmentDatas;
    private ArrayList<String> conversationFragmentDatas;
    private ArrayList<ContactInformationData> searchDatas;
    private ArrayList<PluginListviewData> pluginListviewDatas;
    private ArrayList<ChatListviewData> chatListviewDatas;

    // 当前联系人
    private ContactInformationData curentContact;

    // bitmap
    private Bitmap userPhotoBitmap = null;
    private Bitmap photoshowBitmap = null;

    // 文件处理工具,可以考虑单例化
    private KaibesFilesUtil kaibesFilesUtil;

    // 用户名和密码
    private String username, password;

    // 用户详细信息
    private UserInformationData userInformationData;

    // 账号配置
    private SharedPreferences accountPreferences = null;

    // 用户配置
    private SharedPreferences userPreferences = null;

    // Folder and Path
    private File filesFolder = null;
    private File cacheFolder = null;
    private File userFilesFolder = null;
    private File contactFilesFolder = null;
    private File userCacheFolder = null;
    private File contactCacheFolder = null;

    private File searchCacheFolder = null;
    private File contactPhotoFolder = null;

    private File userPhotoPath = null;

    // KaibesActivity
    private KaibesActivity currentActivity;
    private SoundPoolUtil soundPoolUtil = null;
    private HashMap<String, File> uploadfiles;

    private ArrayList<Task> tasks = null;
    private ReentrantLock lock = null;
    private boolean hasMessage = false;

    // 测试用在线用户
    public ArrayList<String> allOnline = null;
    private SocketWorker socketWorker = null;

    public boolean loginAgain = false;

    public static final boolean hasSDCard() {
	return Environment.MEDIA_MOUNTED.equals(Environment
		.getExternalStorageState());
    }

    @Override
    public void onCreate() {
	// setConnectRunable(new ConnectRunable(this));
	soundPoolUtil = new SoundPoolUtil(getApplicationContext());
	reset();
	super.onCreate();
    }

    public void startService() {
	startService(new Intent(getApplicationContext(), KaibesService.class));
    }

    public void stopService() {
	stopService(new Intent(getApplicationContext(), KaibesService.class));
    }

    public void reset() {
	allOnline = new ArrayList<String>();

	accountPreferences = getSharedPreferences("Account",
		Context.MODE_PRIVATE);
	lock = new ReentrantLock();
	tasks = new ArrayList<Task>();
	contactInformationDatas = new HashMap<String, ContactInformationData>();
	tempSearchDatas = new HashMap<String, ContactInformationData>();
	uploadfiles = new HashMap<String, File>();
	kaibesFilesUtil = new KaibesFilesUtil();
	currentActivity = null;
	contactFragmentDatas = new ArrayList<String>();
	conversationFragmentDatas = new ArrayList<String>();
	searchDatas = new ArrayList<ContactInformationData>();
	pluginListviewDatas = new ArrayList<PluginListviewData>();
	chatListviewDatas = new ArrayList<ChatListviewData>();
    }

    public void createDatabaseHelper() {
	setDatabaseHelper(getUsername());
    }

    public void refresh(String fragment, int i) {
	getCurrentActivity().refresh(fragment, i);
    }

    public void refresh(Class<? extends KaibesFragment> fragment, int i) {
	getCurrentActivity().refresh(fragment.getName(), i);
    }

    public void changeFragment(Class<? extends KaibesFragment> FragmentClass) {
	getCurrentActivity().changeFragment(FragmentClass);
    }

    public void sendData(int head, int action, Object... data) {
	socketWorker.sendData(head, action, data);
    }

    public void doWroks() {
	for (int i = 0; i < tasks.size(); i++) {
	    tasks.remove(i).doWork();
	}
    }

    public void doWork(final Task task) {
	lock.lock();
	try {
	    while (tasks.size() > 0) {
		Thread.sleep(100);
	    }
	} catch (InterruptedException e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
	} finally {
	    task.doWork();
	    lock.unlock();
	}
    }

    // ---------------------------GET AND SET 1--------------------------
    public Bitmap getContactBitmap(String photoName) {
	String photoPath = "";
	if (photoName.equals(StaticValuesUtil.PHOTO_DEAFULT)
		|| (photoPath = getContactPhotoPath(photoName)).equals("")) {
	    return BitmapFactory.decodeResource(getResources(),
		    R.drawable.photo_default);
	} else {
	    return BitmapUtil
		    .toRoundBitmap(BitmapFactory.decodeFile(photoPath));
	}
    }

    public void setSearchPhotoImage(RoundImageView contactPhoto,
	    String photoName) {
	String photoPath = "";
	if (photoName.equals(StaticValuesUtil.PHOTO_DEAFULT)
		|| (photoPath = getSearchPhotoPath(photoName)).equals("")) {
	    contactPhoto.setImageResource(R.drawable.photo_default);
	} else {
	    contactPhoto.setImageBitmap(BitmapFactory.decodeFile(photoPath));
	}
    }

    public void setContactPhotoImage(RoundImageView contactPhoto,
	    String photoName) {
	String photoPath = "";
	if (photoName.equals(StaticValuesUtil.PHOTO_DEAFULT)
		|| (photoPath = getContactPhotoPath(photoName)).equals("")) {
	    contactPhoto.setImageResource(R.drawable.photo_default);
	} else {
	    contactPhoto.setImageBitmap(BitmapFactory.decodeFile(photoPath));
	}
    }

    public void setSearchPhotoImageOrGray(RoundImageView contactPhoto,
	    ContactInformationData contactInformationData) {
	setPhotoImageOrGray(contactPhoto, contactInformationData,
		getSearchPhotoPath(contactInformationData.getPhoto()));
    }

    public void setContactPhotoImageOrGray(RoundImageView contactPhoto,
	    ContactInformationData contactInformationData) {
	setPhotoImageOrGray(contactPhoto, contactInformationData,
		getContactPhotoPath(contactInformationData.getPhoto()));
    }

    public void setPhotoImageOrGray(RoundImageView contactPhoto,
	    ContactInformationData contactInformationData, String photoPath) {
	String photoName = contactInformationData.getPhoto();
	Bitmap bitmap = null;

	if (!photoName.equals(StaticValuesUtil.PHOTO_DEAFULT)
		&& !photoPath.equals("")) {
	    bitmap = BitmapFactory.decodeFile(photoPath);
	}

	if (bitmap == null) {
	    bitmap = BitmapFactory.decodeResource(getResources(),
		    R.drawable.photo_default);
	    contactPhoto.setImageResource(R.drawable.photo_default);
	}

	if (contactInformationData.isOnline()) {
	    contactPhoto.setImageBitmap(bitmap);
	} else {
	    contactPhoto.setImageBitmapGray(bitmap);
	}
    }

    private void setRootFolder() {
	// File root = new File("/storage/sdcard1");

	// if (root.exists()) {
	// setFilesFolder(new File(root, "Android/data/" + getPackageName()
	// + File.separator + StaticValuesUtil.FILES + File.separator
	// + getUsername()));
	// setCacheFolder(new File(root, "Android/data/" + getPackageName()
	// + File.separator + StaticValuesUtil.CACHE));
	// } else {

	if ((filesFolder = getExternalFilesDir(getUsername())) == null) {
	    filesFolder = new File(getFilesDir(), getUsername());
	}

	if ((cacheFolder = getExternalCacheDir()) == null) {
	    cacheFolder = getCacheDir();
	}

	// }

	if (!getFilesFolder().exists()) {
	    getFilesFolder().mkdirs();
	}

	if (!getCacheFolder().exists()) {
	    getCacheFolder().mkdirs();
	}

	setUserFilesFolder();
	setContactFilesFolder();

	setUserCacheFolder();
	setContactCacheFolder();

	setSearchCacheFolder();
    }

    public boolean isMainActivity() {
	return getCurrentActivity() instanceof MainActivity;
    }

    public boolean isLoginActivity() {
	return getCurrentActivity() instanceof LoginActivity;
    }

    // ---------------------------GET AND SET 2--------------------------

    // DatabaseHelper
    public KaibesDataHelper getDatabaseHelper() {
	return databaseHelper;
    }

    public void setDatabaseHelper(String database) {
	databaseHelper = new KaibesDataHelper(getApplicationContext(), database);
    }

    // ContactInformationDatas
    public ContactInformationData getContactInformationData(String contactname) {
	return contactInformationDatas.get(contactname);
    }

    public void removeContactInformationData(String contactname) {
	contactInformationDatas.remove(contactname);
    }

    public void addContactInformationData(
	    ContactInformationData contactInformationData) {
	contactInformationDatas.put(contactInformationData.getContactname(),
		contactInformationData);
    }

    // ContactFragmentData
    public void moveContactFragment2End(int index) {
	String contactname = getContactFragmentDatas().get(index);
	getContactFragmentDatas().add(contactname);
	getContactFragmentDatas().remove(index);
    }

    public void moveContactFragment2End(String contactname) {
	getContactFragmentDatas().remove(contactname);
	getContactFragmentDatas().add(contactname);
    }

    public void moveContactFragment2Top(String contactname) {
	getContactFragmentDatas().remove(contactname);
	getContactFragmentDatas().add(0, contactname);
    }

    public void removeContactFragmentData(String contactname) {
	getContactFragmentDatas().remove(contactname);
	if (getChatListviewDatas().contains(contactname)) {
	    removeConversationFragmentData(contactname);
	}
	removeContactInformationData(contactname);
    }

    public void removeContactFragmentData() {
	removeContactFragmentData(getCurentContact().getContactname());
	getDatabaseHelper().deleteContactinformation(
		getCurentContact().getContactname());
	getContactFragmentDatas().remove(getCurentContact());
    }

    public void addContactFragmentData(String contactname) {
	getContactFragmentDatas().add(contactname);
    }

    public void addContactFragmentDataHead(String contactname) {
	getContactFragmentDatas().add(0, contactname);
    }

    public int getContactFragmentDatasSize() {
	return getContactFragmentDatas().size();
    }

    public ArrayList<String> getContactFragmentDatas() {
	return contactFragmentDatas;
    }

    // ConversationFragmentData
    public void addConversationFragmentData(String contactname) {
	// getContactInformationData(contactname).setExitstConversation(true);
	if (!getConversationFragmentDatas().contains(contactname)) {
	    getConversationFragmentDatas().add(contactname);
	}
    }

    public void addConversationFragmentData() {
	addConversationFragmentData(getCurentContact().getContactname());
    }

    public void removeConversationFragmentData(int index) {
	getConversationFragmentDatas().remove(index);
    }

    public void removeConversationFragmentData(String contactname) {
	getConversationFragmentDatas().remove(contactname);
    }

    public ArrayList<String> getConversationFragmentDatas() {
	return conversationFragmentDatas;
    }

    // searchData
    public ArrayList<ContactInformationData> getSearchDatas() {
	return searchDatas;
    }

    // PluginListviewData
    public ArrayList<PluginListviewData> getPluginListviewDatas() {
	return pluginListviewDatas;
    }

    // ChatListviewData
    public ArrayList<ChatListviewData> getChatListviewDatas() {
	return chatListviewDatas;
    }

    // ContactInformationData
    public void setCurentContact(String contactname) {
	this.curentContact = contactInformationDatas.get(contactname);
    }

    public ContactInformationData getCurentContact() {
	return curentContact;
    }

    public void setCurrentContact(
	    ContactInformationData contactInformationData) {
	this.curentContact = contactInformationData;
    }

    // UserPreferences
    public SharedPreferences getUserPreferences() {
	return userPreferences;
    }

    private void setUserPreferences() {
	this.userPreferences = getSharedPreferences(getUsername(),
		Context.MODE_PRIVATE);
    }

    // Username and Password
    public String getUsername() {
	return username;
    }

    public void setUsername(String username) {
	setUsernameNotCreate(username);
	setUserPreferences();
	setRootFolder();
    }

    public void setUsernameNotCreate(String username) {
	this.username = username;
    }

    public String getPassword() {
	return password;
    }

    public void setPassword(String password) {
	this.password = password;
    }

    // UserInformationData
    public UserInformationData getUserInformationData() {
	return userInformationData;
    }

    public void setUserInformationData(UserInformationData userInformationData) {
	this.userInformationData = userInformationData;
	setUsername(getUserInformationData().getUsername());
    }

    // CacheFolder
    public File getCacheFolder() {
	return cacheFolder;
    }

    // FilesFolder
    public File getFilesFolder() {
	return filesFolder;
    }

    // UserFilesFolder
    public File getUserFilesFolder() {
	return userFilesFolder;
    }

    private void setUserFilesFolder() {
	this.userFilesFolder = new File(getFilesFolder(), StaticValuesUtil.USER);
	if (!userFilesFolder.exists()) {
	    userFilesFolder.mkdir();
	}
    }

    // ContactFilesFolder
    public File getContactFilesFolder() {
	return contactFilesFolder;
    }

    private void setContactFilesFolder() {
	this.contactFilesFolder = new File(getFilesFolder(),
		StaticValuesUtil.CONTACT);
	if (!contactFilesFolder.exists()) {
	    contactFilesFolder.mkdir();
	}

	setContactPhotoFolder();
    }

    // UserCacheFolder
    public File getUserCacheFolder() {
	return userCacheFolder;
    }

    private void setUserCacheFolder() {
	this.userCacheFolder = new File(getCacheFolder(), StaticValuesUtil.USER);
	if (!userCacheFolder.exists()) {
	    userCacheFolder.mkdir();
	}
    }

    // ContactCacheFolder
    public File getContactCacheFolder() {
	return contactCacheFolder;
    }

    private void setContactCacheFolder() {
	this.contactCacheFolder = new File(getCacheFolder(),
		StaticValuesUtil.CONTACT);
	if (!contactCacheFolder.exists()) {
	    contactCacheFolder.mkdir();
	}
    }

    // UserPhotoPath
    public File getUserPhotoPath() {
	return userPhotoPath;
    }

    public void setUserPhotoPath(String photoName) {

	setUserPhotoPathAndNotCreate(photoName);

	if (getUserPhotoPath().exists()) {
	    setUserPhotoBitmap(BitmapFactory.decodeFile(getUserPhotoPath()
		    .getPath()));
	} else if (photoName.equals(StaticValuesUtil.PHOTO_DEAFULT)) {
	    setUserPhotoBitmap(BitmapFactory.decodeResource(getResources(),
		    R.drawable.photo_default));
	} else {

	    getKaibesFilesUtil().addKabesFile(
		    new KaibesFile(getUserCacheFolder(), StaticValuesUtil.PHOTO
			    + File.separator + photoName));
	    getKaibesFilesUtil().getKaibesFile(photoName).open()
		    .setType(StaticValuesUtil.USER_PHOTO);

	    sendData(1, SocketWorker.ACTION_FILE_INFO, getUsername(),
		    photoName, StaticValuesUtil.PHOTO, getKaibesFilesUtil()
			    .getKaibesFile(photoName).length());
	}
    }

    public void setUserPhotoPathAndNotCreate(String photoName) {
	this.userPhotoPath = new File(getUserFilesFolder(),
		StaticValuesUtil.PHOTO + File.separator + photoName);
	if (!userPhotoPath.getParentFile().exists()) {
	    userPhotoPath.getParentFile().mkdir();
	}
    }

    // UserPhotoBitmap
    public Bitmap getUserPhotoBitmap() {
	return userPhotoBitmap;
    }

    public void setUserPhotoBitmap(Bitmap userPhotoBitmap) {
	this.userPhotoBitmap = userPhotoBitmap;
    }

    // PhotoshowBitmap
    public Bitmap getPhotoshowBitmap() {
	return photoshowBitmap;
    }

    public void setPhotoshowBitmap(Bitmap photoshowBitmap) {
	this.photoshowBitmap = photoshowBitmap;
    }

    // KaibesFilesUtil
    public KaibesFilesUtil getKaibesFilesUtil() {
	return kaibesFilesUtil;
    }

    public SoundPoolUtil getSoundPoolUtil() {
	return soundPoolUtil;
    }

    public HashMap<String, File> getUploadfiles() {
	return uploadfiles;
    }

    public KaibesActivity getCurrentActivity() {
	return currentActivity;
    }

    public void setCurrentActivity(KaibesActivity currentActivity) {
	this.currentActivity = currentActivity;
    }

    public SharedPreferences getAccountPreferences() {
	return accountPreferences;
    }

    private void setContactPhotoFolder() {
	this.contactPhotoFolder = new File(getContactFilesFolder(),
		StaticValuesUtil.PHOTO);
	if (!contactPhotoFolder.exists()) {
	    contactPhotoFolder.mkdir();
	}
    }

    private String getSearchPhotoPath(String photoName) {
	File photo = new File(getSearchCacheFolder(), File.separator
		+ StaticValuesUtil.PHOTO + File.separator + photoName);
	if (photo.exists() && photo.length() > 0) {
	    return photo.getPath();
	} else {
	    return "";
	}
    }

    private String getContactPhotoPath(String photoName) {
	File photo = new File(contactPhotoFolder, photoName);
	if (photo.exists() && photo.length() > 0) {
	    return photo.getPath();
	} else {
	    return "";
	}
    }

    public ContactInformationData removeTempSearchData(String contactname) {
	return tempSearchDatas.remove(contactname);
    }

    public void putTempSearchData(String contactname) {
	addContactInformationData(tempSearchDatas.get(contactname));
	addContactFragmentData(contactname);

	ContactInformationData contactInformationData = removeTempSearchData(contactname);

	getDatabaseHelper().replaceContactinformation(
		new String[] { contactInformationData.getContactname(),
			contactInformationData.getNickname(),
			contactInformationData.getPhoto(),
			contactInformationData.getSex(),
			contactInformationData.getBirth(),
			contactInformationData.getSignature(),
			contactInformationData.getIntroduction(),
			contactInformationData.getJob(),
			contactInformationData.getCompany(),
			contactInformationData.getSchool(),
			contactInformationData.getAddress(),
			contactInformationData.getHometown(),
			contactInformationData.getEmail(),
			contactInformationData.getRemark() });

	if (!contactInformationData.getPhoto().equals(
		StaticValuesUtil.PHOTO_DEAFULT)) {
	    File searchPhoto = new File(getSearchCacheFolder(), File.separator
		    + StaticValuesUtil.PHOTO + File.separator
		    + contactInformationData.getPhoto());
	    File contactPhoto = new File(contactPhotoFolder,
		    contactInformationData.getPhoto());

	    if (!contactPhoto.getParentFile().exists()) {
		contactPhoto.getParentFile().mkdir();
	    }
	    searchPhoto.renameTo(contactPhoto);
	}

	refresh(KaibesFragment.MAIN_FRAGMENT, MainFragment.REFRESH_CONTACTS);
    }

    public void addTempSearchData(ContactInformationData contactInformationData) {
	tempSearchDatas.put(contactInformationData.getContactname(),
		contactInformationData);
	getSearchDatas().remove(contactInformationData);
	refresh(KaibesFragment.SEARCH_RESULT_FRAGMENT, 0);
    }

    public File getSearchCacheFolder() {
	return searchCacheFolder;
    }

    private void setSearchCacheFolder() {
	this.searchCacheFolder = new File(getCacheFolder(),
		StaticValuesUtil.SEARCH);
	if (!userCacheFolder.exists()) {
	    userCacheFolder.mkdir();
	}
    }

    public void addTask(Task task) {
	tasks.add(task);
    }

    public boolean isHasMessage() {
	return hasMessage;
    }

    public void setHasMessage(boolean hasMessage) {
	this.hasMessage = hasMessage;
    }

    public void setSocketWorker(SocketWorker socketWorker) {
	this.socketWorker = socketWorker;
    }

    public boolean isLoginAgain() {
	return loginAgain;
    }

    public void setLoginAgain(boolean loginAgain) {
	this.loginAgain = loginAgain;
    }

}
